import Web3 from "web3";
import { providers } from "ethers";
import WalletConnectProvider from "@walletconnect/web3-provider";
import IconMetamask from "@/assets/wallet/icon-metamask.svg";
import IconBscWallet from "@/assets/wallet/icon-bscwallet.svg";
import IconWalletConnect from "@/assets/wallet/icon-walletconnect.svg";
import { getChainById, getChainByCode } from "@/config/chain";

const errors = {
  NoBrowserWallet: "no Browser Wallet",
  NoBsc: "no bsc wallet",
  ChainCodeNotMath: "chainCode not match",
  ChainIdNotMath: "chainId not match",
};

export const rpc = {
  69: "https://kovan.optimism.io",
  420: "https://goerli.optimism.io",
  10: "https://mainnet.optimism.io",
  25: "https://evm.cronos.org",
  56: "https://bsc-dataseed1.binance.org",
  66: "https://exchainrpc.okex.org",
  100: "https://rpc.xdaichain.com",
  128: "https://http-mainnet.hecochain.com",
  137: "https://rpc-mainnet.maticvigil.com",
  250: "https://rpcapi.fantom.network",
  288: "https://mainnet.boba.network",
  1285: "https://rpc.moonriver.moonbeam.network",
  42161: "https://arb1.arbitrum.io/rpc",
  421611: "https://rinkeby.arbitrum.io/rpc",
  43114: "https://api.avax.network/ext/bc/C/rpc",
  1313161554: "https://mainnet.aurora.dev",
  1666600000: "https://api.harmony.one",
};

export const infuraId = "61797cf139924ad5adbdbf5b25075fea";

export const metamask = async (chainCode) => {
  const chain = getChainByCode(chainCode);
  if (!chain) {
    throw new Error(errors.ChainCodeNotMath);
  }
  if (!(window.ethereum && window.ethereum.isMetaMask)) {
    throw new Error(errors.NoMetamask);
  }
  const sdk = new Web3(window.ethereum);
  const accounts = await sdk.eth.requestAccounts();
  const currentChainId = await sdk.eth.getChainId();
  const { chainId } = chain;
  if (chainId && currentChainId !== chainId) {
    await tryConnect(chainId);
  }
  return {
    chainId,
    account: accounts[0],
    sdk
  };
};

export const bscwallet = async (chainCode) => {
  const chain = getChainByCode(chainCode);
  if (!chain) {
    throw new Error(errors.ChainCodeNotMath);
  }
  if (!window.BinanceChain) {
    throw new Error(errors.NoBsc);
  }
  const sdk = new Web3(window.BinanceChain);
  const accounts = await sdk.eth.requestAccounts();
  const currentChainId = await sdk.eth.getChainId();
  const { chainId } = chain;
  if (chainId && currentChainId !== chainId) {
    await tryConnect(chainId);
  }
  return {
    chainId: currentChainId,
    account: accounts[0],
    sdk,
  };
};

export const walletconnect = async (chainCode, config) => {
  const chain = getChainByCode(chainCode);
  if (!chain) {
    throw new Error(errors.ChainCodeNotMath);
  }
  const { chainId } = chain;
  const provider = new WalletConnectProvider({
    infuraId,
    chainId,
    rpc,
    ...config,
  });
  await provider.enable();
  const sdk = new Web3(provider);
  const currentChainId = await sdk.eth.getChainId();
  if (chainId && currentChainId !== chainId) {
    await tryConnect(chainId);
  }
  const accounts = await sdk.eth.getAccounts();
  return {
    chainId: currentChainId,
    account: accounts[0],
    sdk,
  };
};

export const tryConnect = async (chainIdNumber) => {
  const chainId = Web3.utils.toHex(chainIdNumber);
  try {
    await ethereum.request({
      method: "wallet_switchEthereumChain",
      params: [{ chainId }],
    });
  } catch (switchError) {
    console.log("switchError", switchError);
    if (switchError.code === 4902) {
      try {
        const chain = getChainById(chainIdNumber);
        const { chainName, nativeCurrency, rpcUrls, blockExplorerUrls } = chain;
        await ethereum.request({
          method: "wallet_addEthereumChain",
          params: [{
            chainId,
            chainName,
            nativeCurrency,
            rpcUrls,
            blockExplorerUrls
          }],
        });
      } catch (addError) {
        console.log("addError", addError);
      }
    }
  }
};

export const WalletList = [
  {
    code: "browserwallet",
    name: "Browser Wallet",
    icon: IconMetamask,
    connect: metamask,
  },
  {
    code: "bscwallet",
    name: "BSC Wallet",
    icon: IconBscWallet,
    connect: bscwallet,
  },
  {
    code: "walletconnect",
    name: "Wallet Connect",
    icon: IconWalletConnect,
    connect: walletconnect,
  },
];
